﻿using CoreDomain.BusinessCore;
using DomainService.IService.MatchFormula;
using Infrastructure.IRepository.Sys;
using Model.BusinessModel.MatchFormula;
using Model.BusinessModel.OutPut;
using Model.BusinessModel.OutPut.sys;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
using System.Text.Json;
using Utility;
using Utility.Enum;

namespace DomainService.Service.MatchFormula
{
    /// <summary>
    /// 匹配公式接口服务实现
    /// </summary>
    public class MatchFormulaService : IMatchFormulaService
    {
        #region 构造实例化

        /// <summary>
        /// 数据规则配置仓储接口
        /// </summary>
        private readonly ISysDataRuleConfigRepository _sysDataRuleConfigRepository;

        /// <summary>
        /// 构造实列化
        /// </summary>
        /// <param name="sysDataRuleConfigRepository"></param>
        public MatchFormulaService(ISysDataRuleConfigRepository sysDataRuleConfigRepository)
        {
            _sysDataRuleConfigRepository = sysDataRuleConfigRepository;
        }

        #endregion

        #region 服务实现

        /// <summary>
        /// 解析匹配公式
        /// </summary>
        /// <param name="matchFormula">匹配公式字符串</param>
        /// <param name="menuId">菜单id</param>
        /// <param name="ruleType">规则类型</param>
        /// <returns>返回解析字符串</returns>
        public ReceiveStatus<AnalysisRuleDataOutPut> AnalysisMatchFormula(string matchFormula, string menuId, int ruleType)
        {
            ReceiveStatus<AnalysisRuleDataOutPut> receiveStatus = new ReceiveStatus<AnalysisRuleDataOutPut>();
            if (string.IsNullOrEmpty(menuId))
                return ExceptionHelper<AnalysisRuleDataOutPut>.CustomExceptionData("所属菜单不能为空！");
            if (string.IsNullOrEmpty(matchFormula))
                return ExceptionHelper<AnalysisRuleDataOutPut>.CustomExceptionData("不存在规则数据！");

            var matchFormulaList = JsonSerializer.Deserialize<List<MatchingDataInput>>(matchFormula);
            var dataRuleConfigList = _sysDataRuleConfigRepository.GetSysDataRuleConfig(menuId).Where(f => f.ConfigType == ruleType).ToList();
            var expression = DataAuthCore.PreviewFormula(matchFormulaList ?? [], dataRuleConfigList);
            AnalysisRuleDataOutPut model = new()
            {
                AnalysisRule = expression.Item1,
                AnalysisRule_CN = expression.Item2,
            };
            receiveStatus.data = new List<AnalysisRuleDataOutPut> { model };
            return receiveStatus;
        }

        /// <summary>
        /// 获取菜单数据按钮权限
        /// </summary>
        /// <param name="input">匹配数据按钮权限模型</param>
        /// <returns></returns>
        public ReceiveStatus<SysButtonDataOutPut> GetMenuDataButtonAuth(MatchingDataButtonAuthInput input)
        {
            ReceiveStatus<SysButtonDataOutPut> receiveStatus = new();
            //把没有赋权限的按钮置灰
            foreach (var item in input.dataButtonList.Where(f => f.RuleIsOpen))
            {
                if (!string.IsNullOrWhiteSpace(item.AnalysisRule))
                {
                    var result = IsHaveButtonAuth(input.dataRow, item.AnalysisRule ?? string.Empty).Result;
                    if (!result)
                        item.IsDisabled = true;
                    else item.IsDisabled = false;
                }
                else
                {
                    item.IsDisabled = false;
                }
            };

            receiveStatus.data = input.dataButtonList;
            receiveStatus.msg = "获取成功";
            return receiveStatus;
        }

        /// <summary>
        /// 是否拥有按钮权限
        /// </summary>
        /// <param name="dataRow">匹配数据</param>
        /// <param name="ruleStr">规则字符串</param>
        /// <returns></returns>
        public Task<bool> IsHaveButtonAuth(string dataRow, string ruleStr)
        {
            if (string.IsNullOrEmpty(dataRow))
                return Task.FromResult(true);
            if (string.IsNullOrEmpty(ruleStr))
                return Task.FromResult(true);
            //创建动态模型
            var td = JsonHelper.DeserializeStringToDictionary<string, object>(dataRow);
            var model = DataAuthCore.CreatModel(td);

            //构建模型属性表达式树
            Type aType = model.GetType();
            var dataParameter = Expression.Parameter(aType);
            //执行表达式树
            var expar = DynamicExpressionParser.ParseLambda(new[] { dataParameter }, typeof(bool), ruleStr).Compile();
            var result = Convert.ToBoolean(expar.DynamicInvoke(model));
            return Task.FromResult(result);

        }

        #endregion

        #region 数据源

        /// <summary>
        /// 获取下拉框数据源
        /// </summary>
        /// <param name="showControlDataSourceEnum">数据源类型</param>
        /// <returns></returns>
        public ReceiveStatus<SelectOutPut> GetSelectData(ShowControlDataSourceEnum showControlDataSourceEnum)
        {
            ReceiveStatus<SelectOutPut> receiveStatus = new();
            try
            {
                List<SelectOutPut> selectList = new List<SelectOutPut>();
                if (showControlDataSourceEnum == ShowControlDataSourceEnum.DataState)
                {
                    selectList.AddRange(GetDataStateList());
                }
                receiveStatus.data = selectList;
                receiveStatus.msg = "获取成功";
            }
            catch (Exception ex)
            {
                receiveStatus.success = false;
                receiveStatus.code = CodeStatuEnum.Error;
                receiveStatus.data = [];
                receiveStatus.msg = string.Format("获取失败：{0}", ex.Message);
            }

            return receiveStatus;
        }

        /// <summary>
        /// 获取数据状态数据源
        /// </summary>
        /// <returns></returns>
        public List<SelectOutPut> GetDataStateList()
        {
            List<SelectOutPut> selectList =
            [
                new SelectOutPut { label = EnumHelper.GetDescription(DataStateEnum.Enable), value = ((int)DataStateEnum.Enable).ToString() },
                new SelectOutPut { label = EnumHelper.GetDescription(DataStateEnum.Stop), value = ((int)DataStateEnum.Stop).ToString() },
                new SelectOutPut { label = EnumHelper.GetDescription(DataStateEnum.Delete), value = ((int)DataStateEnum.Delete).ToString() },
            ];

            return selectList;
        }

        #endregion

    }
}
